package com.shisan.tingshu.common.minio.service.impl;

import com.shisan.tingshu.common.minio.config.MinioProperties;
import com.shisan.tingshu.common.execption.ShisanException;
import com.shisan.tingshu.common.minio.service.FileUploadService;
import com.shisan.tingshu.common.util.MD5;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

//@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    /**
     * 图片文件的上传
     * @param file
     * @return
     */
    @Override
    public String fileUploadService(MultipartFile file) {

        String originalFilename = file.getOriginalFilename();
        String objectKey = "";

        try {
            // 获取到文件内容
            byte[] bytes = file.getBytes();
            String s = new String(bytes); // 将文件内容转换为字符串。此处不能用byte.toString()，因为byte.toString()返回的是byte的地址值
            String prefix = MD5.encrypt(s); // 上面获取到的s非常长，所以可以用MD5加密一下，防止上传到Minio的文件名过长
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
            objectKey = prefix + suffix;
            // 检查上传的文件是否在桶中
            StatObjectArgs.Builder builder = StatObjectArgs.builder();
            StatObjectArgs statObjectArgs = builder
                    .bucket(minioProperties.getBucketName())
                    .object(objectKey)
                    .build();
            minioClient.statObject(statObjectArgs);
            // 该文件已在桶中存在，直接返回文件访问路径
            return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + objectKey;
        } catch (IOException e) {
            log.error("获取不到文件内容。原因：{}", e.getMessage());
            throw new ShisanException(201, "获取不到文件内容");
        } catch (Exception e) {
            // 该文件在桶中不存在，可以上传至Minio
            log.info("文件在桶中不存在，可以上传至Minio");
            try {
                // 将文件上传到桶中
                PutObjectArgs.Builder putObjectArgsBuilder = PutObjectArgs.builder();
                PutObjectArgs putObjectArgs = putObjectArgsBuilder
                        .bucket(minioProperties.getBucketName())
                        .object(objectKey)
                        // 如果文件大小未知，那么给第二个参数传入1，第三个参数传入 5M ~ 5G之间
                        // 如果文件大小已知，那么给第二个参数传入文件大小，第三个参数传入 -1，Minio会自动计算出最优的Chunk大小
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build();
                minioClient.putObject(putObjectArgs);
                log.info("上传至Minio成功");
                // 返回文件访问路径
                return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + file.getOriginalFilename();

            } catch (Exception subE) {
                log.error("上传至Minio失败。原因：{}", e.getMessage());
                throw new ShisanException(201, "上传至Minio失败");
            }
        }
    }
}
